package cn.iocoder.yudao.module.system.tcpserver.protocol1;

import cn.hutool.core.util.HexUtil;
import cn.iocoder.yudao.module.system.dal.dataobject.zkdata.ZkDataDO;
import cn.iocoder.yudao.module.system.tcpserver.pojo.ProtocolConstant;
import cn.iocoder.yudao.module.system.tcpserver.utils.ZkCrcUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;

public class ZkProtocolDecoder extends LengthFieldBasedFrameDecoder {

    private static final int HEADER_SIZE = 10;

    /**
     * @param maxFrameLength      帧的最大长度
     * @param lengthFieldOffset   length字段偏移的地址
     * @param lengthFieldLength   length字段所占的字节长
     * @param lengthAdjustment    修改帧数据长度字段中定义的值，可以为负数 因为有时候我们习惯把头部记入长度,若为负数,则说明要推后多少个字段
     * @param initialBytesToStrip 解析时候跳过多少个长度
     * @param failFast            为true，当frame长度超过maxFrameLength时立即报TooLongFrameException异常，为false，读取完整个帧再报异
     */

    public ZkProtocolDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) {

        super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);

    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        //在这里调用父类的方法,实现指得到想要的部分,我在这里全部都要,也可以只要body部分
        in = (ByteBuf) super.decode(ctx, in);

        if (in == null) {
            return null;
        }
        if (in.readableBytes() < HEADER_SIZE) {
            throw new Exception("字节数不足");
        }
        byte[] oriData = new byte[in.readableBytes()];
        in.getBytes(in.readerIndex(), oriData);

        int head = in.readUnsignedShort();
        if (head != ProtocolConstant.HEAD) {
            return null;
        }

        //读取length字段
        int length = in.readUnsignedShort();

        if (in.readableBytes() != length - 2 - 2) {
            throw new Exception("标记的长度不符合实际长度");
        }
        int receiver = in.readUnsignedShort();
        int sender = in.readUnsignedShort();
        byte type = in.readByte();
//        if ((type & 0xFF)== 0xA5){
//            //heart
//            return null;
//        }
        byte seq = in.readByte();

        //读取body
        byte[] bytes = new byte[length - HEADER_SIZE - 2];
        in.readBytes(bytes);

        byte crc1 = in.readByte();
        byte crc2 = in.readByte();

        ZkDataDO result = new ZkDataDO();
        result.setPacketLength(length);
        result.setDataLength(length - HEADER_SIZE - 2);
//        result.setDataReceiver(Integer.toHexString(receiver));
        result.setDataReceiver(Integer.toHexString(receiver));
        result.setDataSender(Integer.toHexString(sender));
        result.setDataPayload(HexUtil.encodeHexStr(bytes));
        result.setDataType(type & 0xFF);
        result.setDataSeq(seq & 0xFF);
        result.setOriData(HexUtil.encodeHexStr(oriData));
        result.setStatus(0);//待发送数据
        byte[] crc = ZkCrcUtils.getCrc(oriData);
        if (crc[0] != crc1 || crc[1] != crc2) {
            result.setStatus(2);//异常数据
        }
//        return new MyProtocolBean(type, flag, length, new String(bytes, "UTF-8"));
        return result;
    }
}
